﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MotionCS.Controller
{
    public class Smc300Axis : IAxis
    {
        /// <summary>
        /// 轴配置
        /// </summary>
        private AxisConfi config;
        public AxisConfi Config { get => config; }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="axisConfi"></param>
        public Smc300Axis(AxisConfi axisConfi)
        {
            config = axisConfi;
            InitConfi();
        }
        /// <summary>
        /// 初始化轴配置
        /// </summary>
        private void InitConfi()
        {
            // 脉冲模式
            Smc300Api.SetPulseOutmode(config.Axis, config.OutMode);
            Smc300Api.SetCounterInmode(config.Axis, config.IptMode);
            // 脉冲当量
            Smc300Api.SetEquiv(config.Axis, config.OutUnit);
            // 运行速度
            Smc300Api.SetProfileUnit(config.Axis, config.StartSpeed, config.MualSpeed, config.MualSpeed / config.MualAccel, config.MualSpeed / config.MualDecel, 0);
            // 速度曲线
            Smc300Api.SetSProfile(config.Axis, 0, config.Sramp);
            // 报警模式
            Smc300Api.SetAlmMode(config.Axis, config.Alm == -1 ? 0 : 1, config.AlmLevel, 0);
            // 异常停止
            Smc300Api.SetDecStopTime(config.Axis, 0.002);
            // 急停模式
            Smc300Api.SetAxisIoMap(config.Axis, 3, 6, config.Emg, 0.01);
            Smc300Api.SetEmgMode(config.Axis, config.Emg == -1 ? 0 : 1, config.EmgLevel);
            
            if (config.HomeMode != -1)
            {
                // 硬件限位
                Smc300Api.SetElMode(config.Axis, 1, config.ElLevel, 0);
                // 软件限位
                Smc300Api.SetSoftLimit(config.Axis, 1, 0, 0, config.RsLimit, config.FsLimit);
                Smc300Api.SetInpMode(config.Axis, config.Inp == -1 ? 0 : 1, config.InpLevel);
                // 回零模式
                Smc300Api.SetHomePinLogic(config.Axis, 0, 0);
                Smc300Api.SetHomeMode(config.Axis, config.HomeDir, 1, config.HomeMode, 0);
                Smc300Api.SetHomeProfileUnit(config.Axis, config.HomeSpeedL, config.HomeSpeedH, config.HomeAccel, config.HomeDecel);
                Smc300Api.SetHomePositionUnit(config.Axis, 1, config.HomeOffset);
            }
            // 使能伺服
            Smc300Api.WriteSevonPin(config.Axis, 0);
        }
        /// <summary>
        /// 设置手动速度
        /// </summary>
        public void SetMualSpeed()
        {
            Smc300Api.SetProfileUnit(config.Axis, config.StartSpeed, config.MualSpeed, config.MualSpeed / config.MualAccel, config.MualSpeed / config.MualDecel, 0);
        }
        /// <summary>
        /// 设置自动速度
        /// </summary>
        public void SetAutoSpeed()
        {
            Smc300Api.SetProfileUnit(config.Axis, config.StartSpeed, config.AutoSpeed, config.AutoSpeed / config.AutoAccel, config.AutoSpeed / config.AutoDecel, 0);
        }

        public void SetAutoSpeed2()
        {
          
        }
        /// <summary>
        /// 进入回零速度
        /// </summary>
        public void SetHomeSpeed()
        {
            Smc300Api.SetHomeProfileUnit(config.Axis, config.HomeSpeedL, config.HomeSpeedH, config.HomeSpeedH / config.HomeAccel, config.HomeSpeedH / config.HomeDecel);
        }
        /// <summary>
        /// 获取轴运行状态
        /// </summary>
        /// <returns>true-停止 false-运动中</returns>
        public bool IsCheckDone()
        {
            return Smc300Api.CheckDone(config.Axis) == 1;
        }
        /// <summary>
        /// 运动到绝对点
        /// </summary>
        /// <param name="fdis"></param>
        public int MoveAbs(double fdis)
        {
            if (config.HomeMode != -1)
            {
                Smc300Api.PmoveUnit(config.Axis, fdis, 1);
                return 0;
            }
            else
            {
                return -1;
            }
        }
        /// <summary>
        /// 运动到相对点
        /// </summary>
        /// <param name="fdis"></param>
        public int MoveRel(double fdis)
        {
            if (config.HomeMode != -1)
            {
                double rel = config.MoveDir == 0 ? fdis : -fdis;
                Smc300Api.PmoveUnit(config.Axis, rel, 0);
                return 0;
            }
            else
            {
                return -1;
            }
        }
        /// <summary>
        /// 前向运动
        /// </summary>
        /// <param name="dir"></param>
        public int MoveForward()
        {
            int dir = config.MoveDir == 0 ? 1 : 0;
            Smc300Api.Vmove(config.Axis, (ushort)dir);
            return 0;
        }
        /// <summary>
        /// 后向运动
        /// </summary>
        public int MoveBackward()
        {
            int dir = config.MoveDir == 0 ? 0 : 1;
            Smc300Api.Vmove(config.Axis, (ushort)dir);
            return 0;
        }
        /// <summary>
        /// 停止运动
        /// </summary>
        public int MoveStop()
        {
            if (!IsCheckDone())
            {
                Smc300Api.AxisStop(config.Axis, 0);
            }
            return 0;
        }
        /// <summary>
        /// 急停运动
        /// </summary>
        public int EmgStop()
        {
            if (!IsCheckDone())
            {
                Smc300Api.AxisStop(config.Axis, 1);
            }
            return 0;
        }
        /// <summary>
        /// 回零运动
        /// </summary>
        public int MoveHome()
        {
            if (config.HomeMode != -1)
            {
                SetHomeSpeed();
                Smc300Api.HomeMove(config.Axis);
                return 0;
            }
            else
            {
                return -1;
            }
        }
        /// <summary>
        /// 是否回零完成
        /// </summary>
        /// <returns>false 回零中 true 回零成功 </returns>
        public bool IsHomeFinish()
        {
            ushort iValue = 0;
            Smc300Api.GetHomeResult(config.Axis, ref iValue);

            return iValue == 1;
        }
        /// <summary>
        /// 获取状态
        /// </summary>
        /// <returns></returns>
        public MotorStatus GetStatus()
        {
            return new MotorStatus();
        }
        /// <summary>
        /// 是否驱动器报警
        /// </summary>
        /// <returns>false 未报警 true 报警</returns>
        public bool IsAlarm()
        {
            uint state = Smc300Api.AxisIoStatus(config.Axis);
            return (state & 0x1) == 0x1;
        }
        /// <summary>
        /// 是否触发硬件正限位
        /// </summary>
        /// <returns>false 未触发 true 触发</returns>
        public bool IsElFwdLimit()
        {
            uint state = Smc300Api.AxisIoStatus(config.Axis);
            return (state & 0x2) == 0x2;
        }
        /// <summary>
        /// 是否触发硬件负限位
        /// </summary>
        /// <returns>false 未触发 true 触发</returns>
        public bool IsElRevLimit()
        {
            uint state = Smc300Api.AxisIoStatus(config.Axis);
            return (state & 0x04) == 0x04;
        }
        /// <summary>
        /// 是否到位
        /// </summary>
        /// <returns>true 到位 flase 未到位</returns>
        public bool IsEmg()
        {
            uint state = Smc300Api.AxisIoStatus(config.Axis);
            return (state & 0x08) == 0x08;
        }
        /// <summary>
        /// 是否在原点
        /// </summary>
        /// <returns>false 未触发  true 触发</returns>
        public bool IsHomeInOn()
        {
            uint state = Smc300Api.AxisIoStatus(config.Axis);
            return (state & 0x10) == 0x10;
        }
        /// <summary>
        /// 是否软件正限位
        /// </summary>
        /// <returns>false 未触发 true 触发</returns>
        public bool IsSlFwdLimit()
        {
            uint state = Smc300Api.AxisIoStatus(config.Axis);
            return (state & 0x40) == 0x40;
        }
        /// <summary>
        /// 是否软件负限位
        /// </summary>
        /// <returns></returns>
        public bool IsSlRevLimit()
        {
            uint state = Smc300Api.AxisIoStatus(config.Axis);
            return (state & 0x80) == 0x80;
        }
        /// <summary>
        /// 是否到位
        /// </summary>
        /// <returns>true 到位 flase 未到位</returns>
        public bool IsInp()
        {
            uint state = Smc300Api.AxisIoStatus(config.Axis);
            return (state & 0x100) == 0x100;
        }
        /// <summary>
        /// 获取轴IO信号状态
        /// </summary>
        /// <returns></returns>
        public uint GetIoStatus()
        {
            return Smc300Api.AxisIoStatus(config.Axis);
        }
        /// <summary>
        /// 是否伺服准备就绪
        /// </summary>
        /// <returns>false 未就绪 true 就绪</returns>
        public bool IsSevonRdy()
        {
            return Smc300Api.ReadRdyPin(config.Axis) == 1;
        }
        /// <summary>
        /// 是否伺服使能
        /// </summary>
        /// <returns>false 未使能 true 使能</returns>
        public bool IsSevonEnable()
        {
            return Smc300Api.ReadSevonPin(config.Axis) == 0;
        }
        /// <summary>
        /// 是否伺服复位中
        /// </summary>
        /// <returns>false 未复位 true 复位中</returns>
        public bool IsResetOn()
        {
            return Smc300Api.ReadErcPin(config.Axis) == 0;
        }
        /// <summary>
        /// 伺服使能
        /// </summary>
        public void SevonEnable()
        {
            Smc300Api.WriteSevonPin(config.Axis, 0);
        }
        /// <summary>
        /// 伺服失能
        /// </summary>
        public void SevonDisable()
        {
            Smc300Api.WriteSevonPin(config.Axis, 1);
        }
        /// <summary>
        /// 复位使能
        /// </summary>
        public void ResetEnable()
        {
            Smc300Api.WriteErcPin(config.Axis, 1);
        }
        /// <summary>
        /// 复位失能
        /// </summary>
        public void ResetDisable()
        {
            Smc300Api.WriteErcPin(config.Axis, 0);
        }
        /// <summary>
        /// 读取轴报警
        /// </summary>
        /// <returns></returns>
        public int GetAlmStatus()
        {
            var inBit = (int)Smc300Api.AxisIoStatus(config.Axis);
            return ((inBit & (1 << 1)) != 0 || (inBit & (1 << 2)) != 0) ? 1:0 ;
            return (int)Smc300Api.AxisIoStatus(config.Axis) & 0x01;
        }
        /// <summary>
        /// 设置指令位置
        /// </summary>
        /// <param name="dpos"></param>
        public int SetPositionUnit(double dpos)
        {
            if (config.HomeMode != -1)
            {
                Smc300Api.SetPositionUnit(config.Axis, dpos);
                return 0;
            }
            else
            {
                return -1;
            }
        }
        /// <summary>
        /// 获取指令位置
        /// </summary>
        /// <returns></returns>
        public int GetPositionUnit(ref double dpos)
        {
            if (config.HomeMode != -1)
            {
                Smc300Api.GetPositionUnit(config.Axis, ref dpos);
                return 0;
            }
            else
            {
                return -1;
            }
        }
        /// <summary>
        /// 设置编码器反馈位置
        /// </summary>
        /// <param name="mpos"></param>
        public int SetEncoder(double dpos)
        {
            if (config.HomeMode != -1)
            {
                int pulse = (int)(Math.Round(dpos, 3) * config.IptUnit);
                Smc300Api.SetEncoder(config.Axis, pulse);
                return 0;
            }
            else
            {
                return -1;
            }
        }
        /// <summary>
        /// 获取编码器反馈位置
        /// </summary>
        /// <param name="mpos"></param>
        public int GetEncoder(ref double dpos)
        {
            if (config.HomeMode != -1)
            {
                int pulse = Smc300Api.GetEncoder(config.Axis);
                dpos = (double)pulse / config.IptUnit;
                return 0;
            }
            else
            {
                return -1;
            }
        }
        /// <summary>
        /// 设置编码器反馈位置
        /// </summary>
        /// <param name="mpos"></param>
        public int SetEncoderUnit(double dpos)
        {
            if (config.HomeMode != -1)
            {
                Smc300Api.SetEncoderUnit(config.Axis, dpos);
                return 0;
            }
            else
            {
                return -1;
            }
        }
        /// <summary>
        /// 获取编码器反馈位置
        /// </summary>
        /// <param name="mpos"></param>
        public int GetEncoderUnit(ref double dpos)
        {
            if (config.HomeMode != -1)
            {
                Smc300Api.GetEncoderUnit(config.Axis, ref dpos);
                return 0;
            }
            else
            {
                return -1;
            }
        }
        /// <summary>
        /// 轴运动速度
        /// </summary>
        /// <param name="speed"></param>
        public int GetVpSpeed(ref double speed)
        {
            Smc300Api.ReadCurrentSpeedUnit(config.Axis, ref speed);
            return 0;
        }
    }
}
